package org.jgs1904.quickstart.config;

import org.jgs1904.quickstart.handler.MyAccessDeniedHandler;
import org.jgs1904.quickstart.handler.MyForwardAuthenticationFailureHandler;
import org.jgs1904.quickstart.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

/**
 * @author: 默苍璃
 * @date: 2025-06-0515:07
 */
@Configuration
@Order(200)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;


    /**
     * 定义密码编码器 Bean，使用 BCrypt 强哈希算法对密码进行加密
     *
     * @return 返回一个 BCryptPasswordEncoder 实例
     */
    @Bean
    public PasswordEncoder getpasswordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表单提交
        http.formLogin()
                // 自定义登录页面
                .loginPage("/login.html")
                // 当发现/login时认为是登录，必须和表单提交的地址一样。去执行 UserServiceImpl
                .loginProcessingUrl("/login")
                // 登录成功后跳转页面，POST请求
                .successForwardUrl("/toMain")
                // .successHandler(new MyAuthenticationSuccessHandler("http://www.bing.com"))
                // .failureForwardUrl("/toError");
                .failureHandler(new MyForwardAuthenticationFailureHandler("/error.html"));

        http.authorizeRequests()
                // login.html不需要被认证
                .antMatchers("/showLogin").permitAll()
                // .antMatchers("/login.html").permitAll()
                .antMatchers("/login.html").access("permitAll()").antMatchers("/error.html").permitAll().antMatchers("/main.html").access("hasRole('abc')")
                // url拦截
                .antMatchers("/main.html").access("@customPermissionServiceImpl.hasPermission(request,authentication)")
                // .antMatchers("//main.html").hasRole("abc")
                // 所有请求都必须被认证，必须登录后被访问
                .anyRequest().authenticated();

        http.rememberMe()
                // 失效时间，单位秒
                .tokenValiditySeconds(30)
                // 登录逻辑交给哪个对象
                .userDetailsService(userService)
                // 持久层对象
                .tokenRepository(persistentTokenRepository);

        http.logout().logoutUrl("/logout").logoutSuccessUrl("/login.html");

        // 异常处理
        http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);

        // 关闭csrf防护
        // http.csrf().disable();

    }


}
